package com.apexsoft.monitor.front.console.scheme.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.apexsoft.front.common.support.Result;
import com.apexsoft.monitor.front.console.magent.service.MagentThread;
import com.apexsoft.monitor.front.console.magent.service.MonitorThread;
import com.apexsoft.monitor.front.console.scheme.dao.LinkDao;
import com.apexsoft.monitor.front.console.scheme.dao.SchemeDao;
import com.apexsoft.monitor.front.console.scheme.om.Link;
import com.apexsoft.monitor.front.console.scheme.om.Scheme;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.pagination.Pagination;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service("schemeService")
public class SchemeService {
    private static final Logger log = LogManager.getRootLogger();

    @Autowired
    @Qualifier("schemeDao")
    private SchemeDao schemeDao = null;

    @Autowired
    @Qualifier("linkDao")
    private LinkDao linkDao = null;

    /**
    * 分页面查询数据
    * @param page
    * @param schemeName
    * @return
    * @throws Exception
    */
    public JSONObject listByPage(Pagination page, String schemeName) throws Exception {
        JSONObject result = new JSONObject();
        EntityWrapper<Scheme> entityWrapper = new EntityWrapper<>();
        if (StringUtils.isNotBlank(schemeName)) {
            entityWrapper.like("title",schemeName);
        }
        List<Scheme> list = schemeDao.selectPage(page,entityWrapper);
            if(list != null){
                result.put(Result.CODE,Result.SC_0001);
                result.put(Result.NOTE,"查询成功");
                result.put(Result.TOTAL,list.size());
                result.put(Result.ROWS,list);
            }else{
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "查询失败");
            }
                return result;
            }

    /**
    * 新增监控方案
    * @param request
    * @return
    */
    public JSONObject add(HttpServletRequest request){
        JSONObject result = new JSONObject();
        String title = request.getParameter("title");
        String status = request.getParameter("status");
        if(StringUtils.isNotBlank(title)
            && StringUtils.isNotBlank(status)
        ){
            Scheme scheme = new Scheme();
            scheme.setTitle(title);
            scheme.setStatus(status);
            try{
                long insertRst = schemeDao.insertScheme(scheme);
                if(insertRst > Result.EC_1000){
                    result.put(Result.CODE, Result.SC_0001);
                    result.put(Result.NOTE, "新增监控方案成功");
                }
            }catch (Exception e){
                log.error("新增监控方案失败："+e.getMessage(), e);
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "新增监控方案失败");
            }
        }else{
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "参数不正确");
        }
        return result;
    }

    /**
    * 更新监控方案
    * @param request
    * @return
    */
    public JSONObject update(HttpServletRequest request){
        JSONObject result = new JSONObject();
        String id = request.getParameter("id");
        String title = request.getParameter("title");
        String scheme_code = request.getParameter("schemeCode");
        String status = request.getParameter("status");
        if(
            StringUtils.isNotBlank(title)
            && StringUtils.isNotBlank(scheme_code)
            && StringUtils.isNotBlank(status)
        ){
            Scheme scheme = new Scheme();
            scheme.setId(Integer.parseInt(id));
            scheme.setSchemeCode(scheme_code);
            scheme.setStatus(status);
            scheme.setTitle(title);
            try {
                int uptRst = schemeDao.updateSelectiveById(scheme);
                if(uptRst > Result.EC_1000){
                    result.put(Result.CODE, Result.SC_0001);
                    result.put(Result.NOTE, "修改监控方案成功");
                }
            }catch (Exception e){
                log.error("修改监控方案失败："+e.getMessage(), e);
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "修改监控方案失败");
            }
        }
        return result;
    }

    /**
     * 根据链路起止结点,获取结点Code
     * @param nodesObje
     * @return
     */
    private String getNodeCodeForLink(JSONObject nodesObje,String node){
        String nodeCode = "";
        for (Map.Entry<String, Object> entry : nodesObje.entrySet()) {
            String node_code = entry.getKey();
            if(node_code.equals(node)){
                JSONObject valObj = nodesObje.getJSONObject(node_code);
                nodeCode = valObj.getString("nodeCode")==null?"":valObj.getString("nodeCode");
                return nodeCode;
            }
        }
        return nodeCode;
    }

    /**
     * 保存链路
     * @param jsonStr
     * @return
     */
    public JSONObject saveLink(String schemeCode,String jsonStr){
        JSONObject result = new JSONObject();
        try {
            JSONObject schemeJson = JSONObject.parseObject(jsonStr);
            JSONObject nodesObject = schemeJson.getJSONObject("nodes"); //节点列表
            JSONObject linkObject = schemeJson.getJSONObject("lines"); //链路列表
            //删除指定方案的链路对象
            HashMap<String,Object> paramMap = new HashMap<>();
            paramMap.put("scheme_code",schemeCode);
            linkDao.deleteByMap(paramMap);
            //添加新增的内容
            for (Map.Entry<String, Object> entry : linkObject.entrySet()) {
                String link_code = entry.getKey();   //链路编号
                JSONObject valObj = linkObject.getJSONObject(link_code);
                String start_node = getNodeCodeForLink(nodesObject,valObj.getString("from"));  //开始节点
                String end_node = getNodeCodeForLink(nodesObject,valObj.getString("to"));      //结束节点
                //只有开始和结束结点都有nodeCode的情况下才进行保存.
                if(StringUtils.isNotBlank(start_node) && StringUtils.isNotBlank(end_node)){
                    Link link = new Link();
                    link.setSchemeCode(schemeCode);
                    link.setStartNode(start_node);
                    link.setEndNode(end_node);
                    link.setLinkCode(link_code);
                    linkDao.insert(link);
                }
            }
            result.put(Result.CODE, Result.SC_0001);
            result.put(Result.NOTE, "保存链路信息成功");
        }catch (JSONException e) {
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "保存链路信息失败");
        }
        return result;
    }

    /**
     * 更新拓扑图内容
     * @param request
     * @return
     */
    public JSONObject updateContent(HttpServletRequest request){
        JSONObject result = new JSONObject();
        String schemeCode = request.getParameter("schemeCode");
        String content = request.getParameter("content");
        if(StringUtils.isNotBlank(schemeCode)
                && StringUtils.isNotBlank(content)){
            content = setLineNodeCodeInfo(content);
            HashMap<String,String> param = new HashMap<>();
            param.put("schemeCode",schemeCode);
            param.put("content",content);
            try{
                int uptRst = schemeDao.updateContent(param);
                if(uptRst > Result.EC_1000){
                    result.put(Result.CODE, Result.SC_0001);
                    result.put(Result.NOTE, "更新监控方案内容成功");
                }
                JSONObject rsObj = saveLink(schemeCode,content);
                if(rsObj.get("code").equals("-1")){
                    result.put(Result.CODE, Result.EC_1000);
                    result.put(Result.NOTE, "更新监控方案内容成功,但保存链路信息出错");
                }
            }catch (Exception e){
                log.error("更新监控方案内容失败："+e.getMessage(), e);
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "更新监控方案内容失败");
            }
        }else{
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "参数不正确");
        }
        return result;
    }

    /**
     * 设置链路中的startNodeCode 和 endNodeCode的信息
     * @param content
     * @return
     */
    private String setLineNodeCodeInfo(String content){
        JSONObject schemeJson = JSONObject.parseObject(content);
        JSONObject nodesObject = schemeJson.getJSONObject("nodes"); //节点列表
        JSONObject linkObject = schemeJson.getJSONObject("lines"); //链路列表
        for (Map.Entry<String, Object> entry : linkObject.entrySet()) {
            JSONObject valObj = linkObject.getJSONObject(entry.getKey());
            String start_node = getNodeCodeForLink(nodesObject,valObj.getString("from"));  //开始节点
            String end_node = getNodeCodeForLink(nodesObject,valObj.getString("to"));      //结束节点
            valObj.put("startNodeCode",start_node);
            valObj.put("endNodeCode",end_node);
            linkObject.put(entry.getKey(),valObj);
        }
        schemeJson.put("lines",linkObject);
        return JSONObject.toJSONString(schemeJson);
    }

    /**
     * 获取拓扑图内容
     * @param request
     * @return
     */
    public JSONObject getContent(HttpServletRequest request){
        JSONObject result = new JSONObject();
        String schemeCode = request.getParameter("schemeCode");
        if(StringUtils.isNotBlank(schemeCode)){
            try{
                Scheme scheme = getByCode(schemeCode);
                if(scheme!=null){
                    result.put(Result.OBJECT,scheme);
                    result.put(Result.CODE, Result.SC_0001);
                    result.put(Result.NOTE, "查贸易监控方案内容成功");
                }else{
                    result.put(Result.CODE, Result.EC_1000);
                    result.put(Result.NOTE, "查询监控方案内容失败");
                }
            }catch (Exception e){
                log.error("查询监控方案内容失败："+e.getMessage(), e);
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "查询监控方案内容失败");
            }
        }else{
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "参数不正确");
        }
        return result;
    }

    /**
     * 获取所有状态正常的监控方案
     * @return
     */
    public JSONObject getAllScheme(){
        JSONObject result = new JSONObject();
        try{
            List<Scheme> list = getAllScheme("1");
            result.put(Result.ROWS,list);
            result.put(Result.CODE, Result.SC_0001);
            result.put(Result.NOTE, "查贸易监控方案内容成功");
        }catch (Exception e){
            log.error("查询监控方案列表失败："+e.getMessage(), e);
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "查询监控方案列表失败");
        }
        return result;
    }

    /**
    * 删除监控方案
    * @param id
    * @return
    */
    public JSONObject delete(String id){
        JSONObject result = new JSONObject();
        if(StringUtils.isNotBlank(id)){
            try {
                Scheme scheme = schemeDao.selectById(id);
                int delRst = schemeDao.deleteById(id);
                if(delRst>Result.EC_1000){
                    int delLinkRst = linkDao.deleteByScheme(scheme.getSchemeCode());
                    if(delLinkRst>Result.EC_1000){
                        result.put(Result.CODE, Result.SC_0001);
                        result.put(Result.NOTE, "删除监控方案成功");
                    }else{
                        result.put(Result.CODE, Result.EC_1000);
                        result.put(Result.NOTE, "删除监控方案成功,但删除链路信息失败");
                    }
                }else{
                    result.put(Result.CODE, Result.EC_1000);
                    result.put(Result.NOTE, "删除监控方案失败");
                }
            }catch (Exception e){
                log.error("删除监控方案失败："+e.getMessage(), e);
                result.put(Result.CODE, Result.EC_1000);
                result.put(Result.NOTE, "删除监控方案失败");
            }
        }
        return result;
    }



    /**
    * 查询单条记录
    * @param id
    * @return
    */
    public Scheme getById(int id){
        return schemeDao.selectById(id);
    }

    /**
     * 查询单条记录
     * @param code
     * @return
     */
    public Scheme getByCode(String code){
        Scheme scheme = new Scheme();
        EntityWrapper<Scheme> entityWrapper = new EntityWrapper<>();
        entityWrapper.and("scheme_code={0}",code);
        List<Scheme> list = schemeDao.selectList(entityWrapper);
        if(list!=null){
            if(list.size()>0){
                scheme = list.get(0);
            }
        }
        return scheme;
    }

    /**
     * 获取所有记录.
     * @return
     */
    public List<Scheme> getAllScheme(String status){
        EntityWrapper<Scheme> entityWrapper = new EntityWrapper<>();
        entityWrapper.and("status={0}",status);
        List<Scheme> list = schemeDao.selectList(entityWrapper);
        return list;
    }

    /**
     * 查询节点信息
     * @param nodeCode
     * @return
     */
    public JSONObject queryNodeDesc(String nodeCode){
        JSONObject result = new JSONObject();
        if(StringUtils.isNotBlank(nodeCode)){
            HashMap<String,String> map = schemeDao.queryNodeDesc(nodeCode);
            result.put(Result.OBJECT,map);
            result.put(Result.CODE, Result.SC_0001);
            result.put(Result.NOTE, "查询节点信息成功");
        }else{
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "参数不正确");
        }
        return result;
    }


    public JSONObject getSchemeByCode(String schemeCode){
        JSONObject result = new JSONObject();
        if(StringUtils.isNotBlank(schemeCode) && MonitorThread.schemeList!=null && MonitorThread.magentMap!=null){
            JSONObject schemeData = new JSONObject();
            JSONArray schemeNodes  = new JSONArray();
            JSONArray schemeLines  = new JSONArray();
            //循环匹配方案
            for(Scheme scheme:MonitorThread.schemeList){
                if(scheme.getSchemeCode().equals(schemeCode)){
                    JSONObject schemeContent = JSONObject.parseObject(scheme.getContent());
                    JSONObject schemeNodeObj = schemeContent.getJSONObject("nodes");
                    Set<String> keys = schemeNodeObj.keySet();
                    //循环方案的节点数据
                    for(String key:keys){
                        JSONObject schemeNodeTemp = new JSONObject();
                        JSONObject schemeNode = schemeNodeObj.getJSONObject(key);
                        schemeNodeTemp.put("node",key);
                        schemeNodeTemp.put("name",schemeNode.getString("name"));
                        schemeNodeTemp.put("status","2");
                        schemeNodeTemp.put("note","节点未启用");

                        Set<String> mapKeys = MonitorThread.magentMap.keySet();
                        //循环线程MAP
                        for(String mapKey :mapKeys){
                            MagentThread mt = (MagentThread)MonitorThread.magentMap.get(mapKey);
                            if(mt!=null && mt.getMagentInfo()!=null){
                                JSONObject magentInfo = mt.getMagentInfo();
                                JSONArray nodeStatusList = magentInfo.getJSONArray("nodeStatusList");
                                //循环心跳包返回的节点状态信息
                                for(int i=0;i<nodeStatusList.size();i++){
                                    JSONObject nodeStatuObj = nodeStatusList.getJSONObject(i);
                                    String node_code = nodeStatuObj.getString("node_code");
                                    if(node_code.equals(schemeNode.getString("nodeCode"))){
                                        schemeNodeTemp.put("status",nodeStatuObj.getString("result_code"));
                                        schemeNodeTemp.put("note",nodeStatuObj.getString("result_note"));
                                    }
                                }
                            }
                        }
                        schemeNodes.add(schemeNodeTemp);
                    }

                    JSONObject schemeLineObj = schemeContent.getJSONObject("lines");
                    Set<String> linesKeys = schemeLineObj.keySet();
                    //循环方案的链路数据
                    for(String lineKey:linesKeys){
                        JSONObject schemeLineTemp = new JSONObject();
                        JSONObject schemeLine = schemeLineObj.getJSONObject(lineKey);
                        schemeLineTemp.put("line",lineKey);
                        schemeLineTemp.put("status","2");
                        schemeLineTemp.put("note","链路未启用");

                        Set<String> mapKeys = MonitorThread.magentMap.keySet();
                        //循环线程MAP
                        for(String mapKey :mapKeys){
                            MagentThread mt = (MagentThread)MonitorThread.magentMap.get(mapKey);
                            if(mt!=null && mt.getMagentInfo()!=null){
                                JSONObject magentInfo = mt.getMagentInfo();
                                JSONArray linkStatusList = magentInfo.getJSONArray("linkStatusList");
                                //循环心跳包返回的链路状态信息
                                for(int i=0;i<linkStatusList.size();i++){
                                    JSONObject lineStatuObj = linkStatusList.getJSONObject(i);
                                    String node_code = lineStatuObj.getString("node_code");
                                    String target = lineStatuObj.getString("target");
                                    if(node_code.equals(schemeLine.getString("startNodeCode")) && target.equals(schemeLine.getString("endNodeCode")) ){
                                        schemeLineTemp.put("status",lineStatuObj.getIntValue("result_code"));
                                        schemeLineTemp.put("note",lineStatuObj.getString("result_note"));
                                    }
                                }
                            }
                        }
                        schemeLines.add(schemeLineTemp);
                    }
                    schemeData.put("schemeCode",schemeCode);
                    schemeData.put("lines",schemeLines);
                    schemeData.put("nodes",schemeNodes);
                    break;
                }
            }
            result.put(Result.CODE, Result.SC_0001);
            result.put(Result.OBJECT,schemeData);
        }else{
            result.put(Result.CODE, Result.EC_1000);
            result.put(Result.NOTE, "参数不正确");
        }
        return result;
    }

    /**
     * 获取Scheme的Code
     * @return
     */
    private String querySchemeCode(){
        HashMap<String,String> map = schemeDao.queryMaxId();
        String strId = map.get("id");
        int intId = Integer.parseInt(strId)+1;
        return "scheme_"+intId;
    }

}
